(function () {
    //轮播图的流程

    //1.定义了一个Carousel的类,里面封装了核心方法
    //=>slide方法 用于控制轮播图的滑动

    //=>mouseEvent 通过点击按钮触发slide滑动

    //2. 添加指示器
    //=>指示器动态创建

    //=>指示器点击高亮

    //=>指示器点击切换图片

    //=>指示器和左右两个点击按钮进行绑定


    //3.有缝轮播边界限制

    //4.无缝轮播

    //=>核心方法 circular
    //=>实现思路=>克隆第一张图片,放到最后一张
    //=>picIndex等于li的length的时候,让ul的位置变为0,并且让index变成1

    //5.无缝轮播和有缝轮播兼容处理代码优化
    //=>通过判断 this.circul来切换有缝和无缝轮播

    //6.自动轮播

    //=>抽离的核心方法 next prev
    //=>设定定时器 调用next
    //=>window.onblur 和 window.onfocus事件 浏览器窗口失去焦点和浏览器窗口获取焦点事件 来控制轮播图的播放

    //问题1:为什么用class

    //1.为了方便继承,拓展属性
    //2.语法常态化
    //3.为了react做铺垫
    //4.全局暴露的命名很少

    //问题2:类里面有没有函数声明优先级
    //类里面的动态方法或者属性都是实例的属性,new的时候会在内存中统一创建出来,可以使用this调用,不分书写顺序

    //问题3:为什么莫名报错 =>使用谷歌浏览器调试

    //获取页面上的元素

    //目前的ul是没有宽度,我们需要获取图宽度,动态计算ul的宽度

    //1.面向对象的变成思维(建厂)

    //让轮播图动起来的核心业务逻辑 -index*marsk视口的宽度

    //滑动动画效果,靠封装的animate.js

    //创建一个叫做carousel的类,这个类负责渲染轮播图,以及出轮播图的核心业务
    //核心类
    class Carousel {
        constructor() {
            //在这里面初始化属性
            //获取页面上的dom元素 marsk ul 每个li arrow箭头
            this.marsk = this.$('marsk')
            // console.log(this.marsk);
            this.uu = this.marsk.children[0];
            //获取所有的li
            this.lis = this.uu.children;
            this.arrow = this.marsk.children[1];
            //获取arrow的两个箭头
            this.leftBtn = this.arrow.children[0]
            this.rightBtn = this.arrow.children[1]
            // console.log(this.uu,this.arrow);
            //有一个初始化的图片索引,用于计算ul移动的距离
            this.picIndex = 0;
            //获取一个li的宽度 500px 因为轮播图的移动,就是通过-this.picIndex*一个li的宽度
            // console.dir(this.marsk)
            this.onePicWidth = this.lis[0].offsetWidth;
            //动态计算ul的宽度,让所有的图片都排一排 liWidth*li的数量
            this.uuWidth = this.lis.length * this.onePicWidth + "px"
            //动态设置给ul
            this.uu.style.width = this.uuWidth;
            //一条属性,用于判断是否开启了无缝轮播
            this.circul = false;

        }
        //一个动态方法,专门用于去获取dom
        $ = id => document.getElementById(id);
        //这个动态方法专门用于处理鼠标事件
        mouseEvent = () => {
            //鼠标移入和移出,让arrow显示或者隐藏
            this.marsk.onmouseenter = () => {
                //目前使用了箭头函数,所以this指向当前Carousel的实例
                this.arrow.style.display = "block"
            }

            this.marsk.onmouseleave = () => {
                this.arrow.style.display = 'none'
            }

            //鼠标的点击事件
            this.leftBtn.onclick = this.prev

            this.rightBtn.onclick = this.next

        }
        //轮播图上一张触发的方法
        prev = () => {
            //ul往右边移动
            this.picIndex--
            //如果this.pickIndex<0就跑出去了,所以在这个时候,我们要把this.picIndex的索引设置为最后一张图的索引,就是this.lis.length-1
            if (this.picIndex < 0 && this.circul) {
                this.picIndex = this.lis.length - 2;
                this.uu.style.left = -(this.lis.length - 1) * this.onePicWidth + 'px';

                // console.log(this.uu.style.left);
            } else {
                // console.log('有缝轮播上一张');
                //有缝轮播的边界判断
                if (this.picIndex < 0) {
                    this.picIndex = this.lis.length - 1
                }
            }

            // console.log(this.picIndex);
            //调用slide让图片运动
            this.slide()
            //调用绑定指示器按钮高亮的方法
            this.bindIndecatorActive()

        }
        //轮播图下一张触发的方法
        next = () => {
            //ul要往左边移动
            this.picIndex++

            //判断 如果this.picIndex===this.lis.length;
            //让图片回到第一张,也就意味着将this.pickIndex设为0
            // console.log(this.lis.length);
            if (this.picIndex === this.lis.length && this.circul) {
                this.picIndex = 1;
                //this.picIndex已经加到了5,立刻让uu的位置放到0
                this.uu.style.left = 0;
            } else {
                //有缝轮播
                // console.log('有缝轮播');
                //有缝轮播的边界判断
                if (this.picIndex === this.lis.length) {
                    //说明滑到了最后一张图
                    this.picIndex = 0
                }
            }

            // console.log(this.picIndex);

            //调用slide让图片运动
            // console.log(this.picIndex);
            this.slide()
            //调用绑定指示器按钮高亮的方法
            this.bindIndecatorActive()
            // if (this.circul) {
            //     console.log(123123);
            //     this.uu.style.left = 0;
            // }
        }
        //一个可复用的方法,用于创建元素
        _c = tagName => document.createElement(tagName)
        //动态方法,专门用于控制图片的滑动
        slide() {
            //计算图片滑动的距离
            // console.log(-this.picIndex);
            animate(this.uu, -this.picIndex * this.onePicWidth)
        }
        //指示器
        showIndecator() { //显示指示器
            ///动态创建指示器
            //创建一个装指示器按钮的父元素
            let indecatorEl = this._c('div');
            indecatorEl.id = 'indecator'
            indecatorEl.className = 'indecator'
            //页面上有多少个li标签,就要创建多少个指示器按钮
            for (let i = 0; i < this.lis.length; i++) {
                let span = this._c('span');
                span.innerText = i + 1;
                //添加到父盒子indecatorEl
                // 给每个span添加一个index = i
                span.index = i;
                //给每个span绑定事件

                span.onclick = () => {
                    // //获取所有创建好的span
                    // let spans = span.parentNode.children;
                    // //排他思想,干掉所有人,留下自己加上indecator-active类名
                    // for (let j = 0; j < spans.length; j++) {
                    //     spans[j].className = ""
                    // }

                    // this.className = "indecator-active"
                    // console.log(i);
                    // console.log(_this.picIndex);
                    this.picIndex = i;//this.picIndex和点击按钮的索引绑定
                    // console.log(this.picIndex);
                    this.slide() //调用轮播图的滑动方法,让图片切换
                    this.bindIndecatorActive()//激活点击指示器按钮
                }

                indecatorEl.appendChild(span);

            }

            //将指示器dom对象添加到当前实例,以便后面图片切换和按钮高亮进行绑定
            this.indecatorEl = indecatorEl;

            //将指示器元素插入到marsk容器
            this.marsk.appendChild(indecatorEl)
            //初次显示指示器的时候,让指示器按钮默认高亮一个
            this.bindIndecatorActive()
        }
        //这个方法用于绑定图片切换的时候,让指示器按钮高亮
        bindIndecatorActive() {
            //判断 如果显示了指示器,才做指示器高亮绑定
            if (this.indecatorEl) {
                let spans = this.indecatorEl.children;
                //排他思想,将所有的指示器按钮类名干掉
                for (let i = 0; i < spans.length; i++) {
                    //清空所有span的类名
                    spans[i].className = "";
                }
                if (this.picIndex === this.lis.length - 1 && this.circul) {
                    // this.picIndex = 0;
                    //手动让index为0的哪一个按钮指示器高亮
                    spans[0].className = "indecator-active"
                    //中断下面逻辑的执行
                    return

                }
                spans[this.picIndex].className = "indecator-active"
            }
        }
        //定义一个方法,用于实现无缝轮播
        circular = () => {
            //克隆第一张图片
            let cloneFirstPic = this.lis[0].cloneNode(true);
            //添加ul中作为最后一张
            this.uu.appendChild(cloneFirstPic);
            //重新计算ul的宽度
            console.log(this.lis);
            this.uu.style.width = this.lis.length * this.onePicWidth + 'px'
            //告诉实例,已经开启了无缝轮播
            this.circul = true;
        }
        //自动轮播
        autoPlay = (timer = 2000) => {
            //存用户首次传入的图片自动轮播的时间间隔
            this.timer = timer;
            //失去焦点的时候,需要清除定时器
            window.onblur = () => {
                if (this.interVal) {
                    clearInterval(this.interVal)
                }
            }
            //获得焦点的时候 重新设置定时器
            window.onfocus = () => {
                //将原本用户传入的间隔时间,再次传入自动轮播
                this.autoPlay(this.timer)
            }
            this.interVal = setInterval(() => {
                this.next()
            }, timer)
        }
     }

    let c = new Carousel()
    c.mouseEvent()
    c.showIndecator()
    c.circular()
    // c.autoPlay(1000)

    //window的获取焦点事件和失去焦点事件

})()